﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

namespace HobSoft.SoccerBet2014.Client.Service
{
    using Domain.ClientService;
    using Domain.DataService;
    using Domain.Factory;
    using Domain.Models;
    using Domain.Models.BfRaw;
    using SoccerBet2014.Common.Errors;

    public class BfRequestService : IBfRequestService
    {
        private readonly IBfManagerFactory managerFactory;
        private readonly IBfCustomDataService bfCustomService;
        private readonly ConcurrentDictionary<string, IBfManagerService> managerService = new ConcurrentDictionary<string, IBfManagerService>();
        public BfRequestService(IBfManagerFactory _managerFactory
                                            , IBfCustomDataService _bfCustomService)
        {
            managerFactory = _managerFactory;
            bfCustomService = _bfCustomService;
        }

        public async Task<bool> Singup(BFAccount account, string certificateFile)
        {
            if (managerService.ContainsKey(account.Account))
            {
                if (managerService[account.Account].LoginInfo.IsLogin) return true;
                return await managerService[account.Account].Signup(certificateFile);
            }
            var manager = managerFactory.CreateOrGet(account);
            managerService.TryAdd(account.Account, manager);
            return await manager.Signup(certificateFile);
        }

        public async Task<IList<MarketBook>> GetMarketBook(params string[] marketIds)
        {
            marketIds.IsNull().ThrowNull("marketIds", "need marketIds");
            var managers = managerService.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();

            if (!marketIds.Any()) return null;

            return await manager.ListMarketBook(marketIds);
        }

        public async Task<PlaceExecutionReport> Betting(string _marketId, PlaceInstruction _placeInstruction, string _customerRef = null)
        {
            var managers = managerService.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();
            return await manager.Betting(_marketId, _placeInstruction, _customerRef);
        }

        public async Task<CancelExecutionReport> CancelOrder(string _marketId, CancelInstruction _instruction, string _customerRef = null)
        {
            var managers = managerService.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();
            return await manager.CancelOrders(_marketId, _instruction, _customerRef);
        }

        public async Task<CurrentOrderSummaryReport> GetOrders()
        {
            var managers = managerService.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();
            return await manager.ListOrders();
        }

        public async Task<BFEvent> GetEventMarkets(int eventId)
        {
            //var managers = managerService.Values.Where(m => m.LoginInfo.IsLogin);
            //if (!managers.Any()) return null;

            var taskEvent= Task.Factory.StartNew(() => bfCustomService.GetEvent(eventId));
            var taskMarket = Task.Factory.StartNew(() => bfCustomService.GetMarkets(eventId));
            await Task.WhenAll(taskEvent, taskMarket);
            var bfEvent = taskEvent.Result;
            var markets = taskMarket.Result;
            bfEvent.Markets = new ObservableCollection<BFMarket>(markets);
            return bfEvent;
        }

        public async Task<IList<BFEvent>> GetEventByMarket(string[] marketIds)
        {
            var taskEvents = Task.Factory.StartNew(() => bfCustomService.GetEventByMarket(marketIds));
            await taskEvents;
            var bfEvents = taskEvents.Result;
            return bfEvents;
        }

        public async Task<bool> HasLogin()
        {
            return managerService.Values.Any(m => m.LoginInfo.IsLogin);
        }

    }
}
